#ifndef _H_PLATFORM_COMMCTRL_H_
#define _H_PLATFORM_COMMCTRL_H_

#pragma once

#include <XLib/UIXCtrl2.h>
#include <Util/ViewObjecter.h>

class TradeButton
	: public UIXButton2Impl<TradeButton>
	, public UIButton2Map<TradeButton>
	, public UIPaint<TradeButton>
{
	typedef TradeButton This;
	typedef UIXButton2Impl<TradeButton> Base;
	typedef UIButton2Map<TradeButton> FuncMap;
	typedef UIPaint<TradeButton> Paint;
protected:
	CString m_strValue;
	COLORREF m_crText;
	COLORREF m_crBackgnd;
	HFONT m_hValue;
public:
	TradeButton();

	BOOL IsDirectUI() { return TRUE; }

	void SetWindowText(LPCTSTR lpszTitle, LPCTSTR lpszValue = NULL);
	void SetColor(COLORREF crText, COLORREF crBackgnd);

	void SetFont(HFONT hFont, HFONT hValue = NULL, BOOL bRedraw = TRUE);

public:
	BOOL OnEraseBkgnd(HDC hdc);
	void OnPaint(HDC hdc);

	BEGIN_MSG_MAP(This)
		CHAIN_MSG_MAP(Paint)
		CHAIN_MSG_MAP(FuncMap)
		CHAIN_MSG_MAP(Base)
	END_MSG_MAP()
};


//////////////////////////////////////////////////////////////////////////

class MyTabCtrl
	: public WndObjecterImpl<MyTabCtrl,UITabCtrl2T<UIXWnd2>>
	, public UITabCtrl2Map<MyTabCtrl>
	, public UIXTabCtrlSkinMap<MyTabCtrl>
{
	typedef MyTabCtrl This;
	typedef WndObjecterImpl<MyTabCtrl,UITabCtrl2T<UIXWnd2>> Base;
	typedef UITabCtrl2Map<MyTabCtrl> FuncMap;
	typedef UIXTabCtrlSkinMap<MyTabCtrl> SkinMap;
	DECLARE_XMLWND_CLASS(_T("MyTabCtrl"))
	DECLARE_DYNCREATE_WND_OBJECTER(MyTabCtrl,Objecter)
public:
	BOOL IsDirectUI() { return TRUE; }

	void Draw(HDC hdc);

	BEGIN_MSG_MAP(This)
		CHAIN_MSG_MAP(FuncMap)
		CHAIN_MSG_MAP(SkinMap)
		CHAIN_MSG_MAP(Base)
	END_MSG_MAP()
};

class TechTabCtrl 
	: public MyTabCtrl
{
public:
};
/*
class MyHeaderCtrl 
	: public WndObjecterImpl<MyHeaderCtrl,UIHeaderCtrl2T<UIXWnd2>>
	, public UIHeaderCtrl2Map<MyHeaderCtrl>
	, public UIXHeaderCtrlSkinMap<MyHeaderCtrl>
{
	typedef MyHeaderCtrl This;
	typedef WndObjecterImpl<MyHeaderCtrl,UIHeaderCtrl2T<UIXWnd2>> Base;
	typedef UIHeaderCtrl2Map<MyHeaderCtrl> FuncMap;
	typedef UIXHeaderCtrlSkinMap<MyHeaderCtrl> SkinMap;
	DECLARE_XMLWND_CLASS(_T("MyHeaderCtrl"))
	DECLARE_DYNCREATE_WND_OBJECTER(MyHeaderCtrl,Objecter)
public:
	BOOL IsDirectUI() { return TRUE; }

	void Draw(HDC hdc);

	BEGIN_MSG_MAP(This)
		CHAIN_MSG_MAP(FuncMap)
		CHAIN_MSG_MAP(SkinMap)
		CHAIN_MSG_MAP(Base)
	END_MSG_MAP()
};

class MyScrollBar 
	: public WndObjecterImpl<MyScrollBar,UIScrollBar2T<UIXWnd2>>
	, public UIScrollBar2Map<MyScrollBar>
	, public UIXScrollBarSkinMap<MyScrollBar>
{
	typedef MyScrollBar This;
	typedef WndObjecterImpl<MyScrollBar,UIScrollBar2T<UIXWnd2>> Base;
	typedef UIScrollBar2Map<MyScrollBar> FuncMap;
	typedef UIXScrollBarSkinMap<MyScrollBar> SkinMap;
	DECLARE_XMLWND_CLASS(_T("MyScrollBar"))
	DECLARE_DYNCREATE_WND_OBJECTER(MyHeaderCtrl,Objecter)
public:
	BOOL IsDirectUI() { return TRUE; }

	void Draw(HDC hdc);

	BEGIN_MSG_MAP(This)
		CHAIN_MSG_MAP(FuncMap)
		CHAIN_MSG_MAP(SkinMap)
		CHAIN_MSG_MAP(Base)
	END_MSG_MAP()
};

class MyListCtrl 
	: public WndObjecterImpl<MyListCtrl,UIListCtrl2T<UIXWnd2>>
	, public UIListCtrl2Map<MyListCtrl>
	//, public UIXListCtrl2SkinMap<MyListCtrl>
{
	typedef MyListCtrl This;
	typedef WndObjecterImpl<MyListCtrl,UIListCtrl2T<UIXWnd2>> Base;
	typedef UIListCtrl2Map<MyListCtrl> FuncMap;
	//typedef UIXListCtrl2SkinMap<MyListCtrl> SkinMap;
	DECLARE_XMLWND_CLASS(_T("MyListCtrl"))
	DECLARE_DYNCREATE_WND_OBJECTER(MyListCtrl,Objecter)
public:

	//MyHeaderCtrl m_wndHeader;

	BOOL IsDirectUI() { return TRUE; }

	BOOL PreCreateWindow(CREATESTRUCT& cs);

	BEGIN_MSG_MAP(This)
		CHAIN_MSG_MAP(FuncMap)
		//CHAIN_MSG_MAP(SkinMap)
		CHAIN_MSG_MAP(Base)
	END_MSG_MAP()
};*/

class MyHeaderCtrl 
	: public UIXWnd2Impl<MyHeaderCtrl,UIHeaderCtrl2>
	, public UIOwnerDraw<MyHeaderCtrl>
{
	typedef MyHeaderCtrl This;
	typedef UIXWnd2Impl<MyHeaderCtrl,UIHeaderCtrl2> Base;
	DECLARE_XMLWND_CLASS(_T("MyHeaderCtrl"))
protected:

public:
	MyHeaderCtrl();
	virtual ~MyHeaderCtrl();

	BEGIN_MSG_MAP(This)
	END_MSG_MAP()

protected:
	void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
	//void DrawFlatBorder(CDC* pDC);
};

class MyListCtrl 
	: public UIXWnd2Impl<MyListCtrl,UIListCtrl2>
{
	typedef MyListCtrl This;
	typedef UIXWnd2Impl<MyListCtrl,UIListCtrl2> Base;
	DECLARE_XMLWND_CLASS(_T("MyListCtrl"))
public:

protected:
	void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
	void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};

//////////////////////////////////////////////////////////////////////////

template<class T, class TListCtrl = UIListCtrl2>
class MyListCtrlMap : public UIBkgnd<T>
{
	typedef MyListCtrlMap<T> This;
protected:
	UINT m_nItemHeight;
	//COLORREF m_crSelBkColor;
	//COLORREF m_crTextSelColor;

public:
	MyListCtrlMap()
	{
		m_nItemHeight = 0;
	}

	TListCtrl GetListCtrl()
	{
		T* pT = static_cast<T*>(this);
		return *pT;
	}

	void UpdateWindowPos()
	{
		T* pT = static_cast<T*>(this);
		TListCtrl wndListCtrl = pT->GetListCtrl();

		CRect rcWnd;
		wndListCtrl.GetWindowRect(&rcWnd);
		WINDOWPOS wp = {0};
		wp.hwnd = *pT;
		wp.cx = rcWnd.Width();
		wp.cy = rcWnd.Height();
		wp.flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER;
		wndListCtrl.SendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp);
	}

	UINT SetItemHeight(UINT nItemHeight)
	{
		T* pT = static_cast<T*>(this);

		UINT nOldItemHeight = m_nItemHeight;
		m_nItemHeight = nItemHeight;

		pT->UpdateWindowPos();

		return nOldItemHeight;
	}

	/*COLORREF SetSelBkColor(COLORREF cr)
	{
		COLORREF crOldColor = m_crSelBkColor;
		m_crSelBkColor = cr;
		return crOldColor;
	}

	COLORREF SetTextSelColor(COLORREF cr)
	{
		COLORREF crOldColor = m_crTextSelColor;
		m_crTextSelColor = cr;
		return crOldColor;
	}

	COLORREF GetSelBkColor()
	{
		return m_crSelBkColor;
	}

	COLORREF GetTextSelColor()
	{
		return m_crTextSelColor;
	}

	COLORREF GetBkColor()
	{
		T* pT = static_cast<T*>(this);
		TListCtrl wndListCtrl = pT->GetListCtrl();
		return wndListCtrl.GetBkColor();
	}*/

	void Relayout()
	{
		T* pT = static_cast<T*>(this);
		TListCtrl wndListCtrl = pT->GetListCtrl();
		if (wndListCtrl != *pT) {
			CRect rcClient;
			pT->GetClientRect(&rcClient);
			wndListCtrl.MoveWindow(&rcClient);
		}
	}

	void OnCacheHint(NMLVCACHEHINT* lpCacheHint)
	{
		
	}

	void OnGetDispInfo(NMLVDISPINFO* lpDispInfo)
	{

	}

	void OnMeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
	{
		lpMeasureItemStruct->itemHeight = m_nItemHeight;
	}

	void OnDrawSubItem(HDC hdc, int nItem, int nSubItem)
	{
		T* pT = static_cast<T*>(this);
		TListCtrl wndListCtrl = pT->GetListCtrl();

		UIHeaderCtrl2 wndHeader = wndListCtrl.GetHeader();
		if (!wndHeader) {
			return;
		}

		RECT rcSubItem = {0};
		if (!wndListCtrl.GetSubItemRect(nItem, nSubItem, LVIR_LABEL, &rcSubItem))   
			return; 

		TCHAR szBuffer[MAX_PATH] = {0};
		LV_ITEM lvi;
		lvi.mask = LVIF_TEXT;
		lvi.iItem = nItem; 
		lvi.iSubItem = nSubItem;
		lvi.pszText = szBuffer;
		lvi.cchTextMax = sizeof(szBuffer);
		wndListCtrl.GetItem(&lvi);

		UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_BOTTOM;
		HD_ITEM hditem = {0};
		hditem.mask = HDI_FORMAT;
		wndHeader.GetItem(nSubItem, &hditem);
		if( hditem.fmt & HDF_CENTER) {
			uFormat |= DT_CENTER;
		} else if( hditem.fmt & HDF_RIGHT) {
			uFormat |= DT_RIGHT;
		} else {
			uFormat |= DT_LEFT;
		}

		DrawText(hdc, lvi.pszText, lstrlen(lvi.pszText), &rcSubItem, uFormat);
	}

	void OnDrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
	{
		T* pT = static_cast<T*>(this);
		TListCtrl wndListCtrl = pT->GetListCtrl();

		UIHeaderCtrl2 wndHeader = wndListCtrl.GetHeader();
		if (!wndHeader) {
			return;
		}
		int nColCount = wndHeader.GetItemCount();

		int nCount = wndListCtrl.GetItemCount();

		CDCHandle dc(lpDrawItemStruct->hDC);

		int nItem =lpDrawItemStruct->itemID;
		CRect rcItem = lpDrawItemStruct->rcItem;

		dc.SetBkMode(TRANSPARENT);
		//dc.FillSolidRect(&rcItem, wndListCtrl.GetBkColor());
		//COLORREF crOldTextBkColor = dc.SetBkColor(pT->GetTextBkColor());
		COLORREF crOldTextColor = CLR_NONE;
		//if (lpDrawItemStruct->itemState & ODS_SELECTED) {
		//	dc.FillSolidRect(rcItem, pT->GetSelBkColor());
		//	crOldTextColor = dc.SetTextColor(pT->GetTextSelColor());
		//} else {
			crOldTextColor = dc.SetTextColor(wndListCtrl.GetTextColor());
		//}

		for (int nCol=0; nCol<nColCount; nCol++)
		{
			pT->OnDrawSubItem(dc, nItem, nCol);
		}

		dc.SetTextColor(crOldTextColor);
		//dc.SetTextColor(crOldTextBkColor);
	}

	BEGIN_MSG_MAP(This)
		MESSAGE_HANDLER(WM_SIZE, OnSize)

		NOTIFY_CODE_HANDLER(LVN_ODCACHEHINT, OnCacheHint)
		NOTIFY_CODE_HANDLER(LVN_GETDISPINFO, OnGetDispInfo)
		MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
		MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)

		REFLECTED_NOTIFY_CODE_HANDLER(LVN_ODCACHEHINT, OnCacheHint)
		REFLECTED_NOTIFY_CODE_HANDLER(LVN_GETDISPINFO, OnGetDispInfo)
		MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)
		MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)

		//CHAIN_MSG_MAP(Base)
		//DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()

	LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);
		if (wParam != SIZE_MINIMIZED && lParam != 0) {
			pT->Relayout();
		}
		return bHandled;
	}

	LRESULT OnCacheHint(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
	{
		T* pT = static_cast<T*>(this);
		NMLVCACHEHINT* pNMLVCH = reinterpret_cast<NMLVCACHEHINT*>(pnmh);
		pT->OnCacheHint(pNMLVCH);
		return 0;
	}

	LRESULT OnGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
	{
		T* pT = static_cast<T*>(this);
		NMLVDISPINFO *pNMLVDI = reinterpret_cast<NMLVDISPINFO*>(pnmh);
		pT->OnGetDispInfo(pNMLVDI);
		return 0;
	}

	LRESULT OnMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);
		LPMEASUREITEMSTRUCT lpMis = (LPMEASUREITEMSTRUCT)lParam;
		pT->OnMeasureItem(lpMis);
		return 0;
	}

	LRESULT OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);
		TListCtrl wndListCtrl = pT->GetListCtrl();

		LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
		pT->OnDrawItem(lpdis);
		return 0;
	}
};

template<class T>
class MyListCtrlExMap : public MyListCtrlMap<T>
{
public:
	typedef MyListCtrlExMap<T> This;
	typedef MyListCtrlMap<T> Base;
protected:
	int m_nFixedRowCount;
	int m_nFixedColumnCount;
public:
	MyListCtrlExMap()
	{

	}

	UINT GetFixedRowCount() { return m_nFixedRowCount; }
	UINT SetFixedRowCount(UINT nCount) 
	{
		UINT nOldCount = m_nFixedRowCount;
		m_nFixedRowCount = nCount;
		return nOldCount;
	}

	UINT GetFixedColumnCount() { return m_nFixedColumnCount; }
	UINT SetFixedColumnCount(UINT nCount) 
	{
		UINT nOldCount = m_nFixedColumnCount;
		m_nFixedColumnCount = nCount;
		return nOldCount;
	}

	void OnGetFixedDispInfo(NMLVDISPINFO* lpDispInfo)
	{

	}

	void OnDrawFixedItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
	{
		Base::OnDrawItem(lpDrawItemStruct);
	}

	BEGIN_MSG_MAP(This)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)

		NOTIFY_CODE_HANDLER(LVN_GETDISPINFO, OnGetDispInfo)
		MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)

		REFLECTED_NOTIFY_CODE_HANDLER(LVN_GETDISPINFO, OnGetDispInfo)
		MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)

		CHAIN_MSG_MAP(Base)
	END_MSG_MAP()

	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;

		T* pT = static_cast<T*>(this);
		pT->ModifyStyle(0, LVS_NOCOLUMNHEADER|LVS_OWNERDATA);
		pT->SetFixedRowCount(1);

		return bHandled;
	}

	LRESULT OnGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
	{
		T* pT = static_cast<T*>(this);
		NMLVDISPINFO *pNMLVDI = reinterpret_cast<NMLVDISPINFO*>(pnmh);
		if (pNMLVDI->item.iItem<GetFixedRowCount()) {
			pT->OnGetFixedDispInfo(pNMLVDI);
		} else {
			pT->OnGetDispInfo(pNMLVDI);
		}
		return 0;
	}

	LRESULT OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);
		TListCtrl wndListCtrl = pT->GetListCtrl();

		LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
		if (lpdis->item.iItem<GetFixedRowCount()) {
			pT->OnDrawFixedItem(lpdis);
		} else {
			pT->OnDrawItem(lpdis);
		}
		return 0;
	}
};


//////////////////////////////////////////////////////////////////////////

#endif//_H_PLATFORM_COMMCTRL_H_